/*
 * ReportManager.java
 *
 * Created on 12 de Mar�o de 2003, 22:39
 */
package saci.reptil;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import javax.swing.table.TableModel;
import java.util.HashMap;

import java.awt.Component;
import java.awt.print.Book;
import java.awt.print.PrinterJob;
import java.awt.print.PrinterException;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.util.Vector;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import java.awt.BorderLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.Color;
import saci.reptil.reader.XmlReader;

/**
 * Classe que gerencia o relat�rio
 *
 * @author  saci
 */
public class ReportManager {

    public static final ReportPaper A4 = new ReportPaper(595.24, 841.85, 30, 30);
    public static final ReportPaper A3 = new ReportPaper(841.85, 1190.49, 30, 30);
    public static final ReportPaper LETTER = new ReportPaper(611.97, 791.96, 30, 30);
    public static final ReportPaper LEGAL = new ReportPaper(611.97, 1007.95, 30, 30);
    public static final int PORTRAIT = PageFormat.PORTRAIT;
    public static final int LANDSCAPE = PageFormat.LANDSCAPE;
    private ReportPaper paper = LETTER;
    private ReportData reportData;
    private DetailBand detailBand;
    private HeaderBand headerBand;
    private FooterBand footerBand;
    private TitleBand titleBand;
    private SummaryBand summaryBand;
    private Group group;
    private Book book;
    private PageFormat pageFormat;
    private Vector componentsInReport;
    private int orientation = PORTRAIT;
    private String fontDirectory;

    /**
     * Cria uma nova inst�ncia da classe
     *
     * @param xml uma inst�ncia da classe XmlReader
     * @param rd a fonte de dados do relat�rio
     */
    public ReportManager(XmlReader xml, ReportData rd) throws ReportException {
        reportData = rd;
        makeReport(xml);
    }

    /**
     * Cria uma nova inst�ncia da classe
     *
     * @param xml uma inst�ncia da classe XmlReader
     * @param conn a conex�o com o banco de dados
     */
    public ReportManager(XmlReader xml, Connection conn) throws ReportException {
        init(xml, conn);
    }

    /**
     * Cria uma nova inst�ncia da classe
     *
     * @param xml uma inst�ncia da classe XmlReader
     */
    public ReportManager(XmlReader xml) throws ReportException {
        Connection conn = xml.getConnection();
        init(xml, conn);

        try {
            if (conn != null) {
                conn.close();
            }
        } catch (Exception e) {
            throw new ReportException(e.toString());
        }

        conn = null;
    }

    private void init(XmlReader xml, Connection conn) throws ReportException {
        if (conn != null) {
            try {
                ResultSet rs = conn.createStatement().executeQuery(xml.getSQL());

                ResultSetMetaData rsm = rs.getMetaData();
                final Vector columns = new Vector();
                final Vector data = new Vector();

                for (int i = 1; i <= rsm.getColumnCount(); i++) {
                    columns.addElement(rsm.getColumnName(i));
                }

                HashMap hash;
                while (rs.next()) {
                    hash = new HashMap();

                    for (int i = 0; i < columns.size(); i++) {
                        hash.put(columns.get(i).toString(), rs.getObject(columns.get(i).toString()));
                    }

                    data.addElement(hash);
                }

                TableModel tableModel = new TableModel() {

                    public Class getColumnClass(int columnIndex) {
                        return ((HashMap) data.get(0)).get(getColumnName(columnIndex)).getClass();
                    }

                    public int getColumnCount() {
                        return columns.size();
                    }

                    public String getColumnName(int columnIndex) {
                        return columns.get(columnIndex).toString();
                    }

                    public int getRowCount() {
                        return data.size();
                    }

                    public Object getValueAt(int rowIndex, int columnIndex) {
                        return ((HashMap) data.get(rowIndex)).get(getColumnName(columnIndex));
                    }

                    public boolean isCellEditable(int rowIndex, int columnIndex) {
                        return false;
                    }

                    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
                    }

                    public void removeTableModelListener(javax.swing.event.TableModelListener tableModelListener) {
                    }

                    public void addTableModelListener(javax.swing.event.TableModelListener tableModelListener) {
                    }
                };

                reportData = new ReportData(tableModel);
            } catch (SQLException e) {
                throw new ReportException(e.getMessage());
            }
        }

        makeReport(xml);
    }

    private void makeReport(XmlReader xml) throws ReportException {
        this.detailBand = xml.getDetailBand();
        this.headerBand = xml.getHeaderBand();
        this.footerBand = xml.getFooterBand();
        this.titleBand = xml.getTitleBand();
        this.summaryBand = xml.getSummaryBand();
        this.group = xml.getGroup();
        this.componentsInReport = xml.getComponentsInReport();
        this.paper = xml.getPaper();
        this.orientation = xml.getOrientation();
        this.fontDirectory = xml.getFontDirectory();
    }

    /**
     * Cria uma nova inst�ncia da classe
     * 
     * @param rd a fonte de dados do relat�rio
     * @param detail a banda detalhe
     * @param header o cabe�alho
     * @param footer o rodap�
     * @param title o titulo do relat�rio
     * @param summary o sum�rio
     * @param group o grupo de dados
     */
    public ReportManager(ReportData rd, DetailBand detail, HeaderBand header, FooterBand footer, TitleBand title, SummaryBand summary, Group group) {
        this.reportData = rd;
        this.detailBand = detail;
        this.headerBand = header;
        this.footerBand = footer;
        this.titleBand = title;
        this.summaryBand = summary;
        this.group = group;
    }

    /**
     * Cria uma nova inst�ncia da classe
     * 
     * @param rd a fonte de dados do relat�rio
     * @param detail a banda detalhe
     * @param header o cabe�alho
     * @param footer o rodap�
     */
    public ReportManager(ReportData rd, DetailBand detail, HeaderBand header, FooterBand footer) {
        this(rd, detail, header, footer, null, null, null);
    }

    /**
     * Cria uma nova inst�ncia da classe
     * 
     * @param rd a fonte de dados do relat�rio
     * @param detail a banda detalhe
     */
    public ReportManager(ReportData rd, DetailBand detail) {
        this(rd, detail, null, null);
    }

    /**
     * Cria uma nova inst�ncia da classe
     * 
     * @param rd a fonte de dados do relat�rio
     */
    public ReportManager(ReportData rd) {
        this(rd, null);
    }

    /**
     * Cria uma nova inst�ncia da classe
     */
    public ReportManager() {
    }

    /**
     * Altera a fonte de dados do relat�rio
     */
    public void setReportData(ReportData rd) {
        reportData = rd;
    }

    /**
     * Altera a banda detalhe (banda de dados)
     */
    public void setDetailBand(DetailBand db) {
        detailBand = db;
    }

    /**
     * Altera o cabe�alho
     */
    public void setHeaderBand(HeaderBand hb) {
        headerBand = hb;
    }

    /**
     * Altera o rodap�
     */
    public void setFooterBand(FooterBand fb) {
        footerBand = fb;
    }

    /**
     * Altera o t�tulo
     */
    public void setTitleBand(TitleBand tb) {
        titleBand = tb;
    }

    /**
     * Altera o sum�rio
     */
    public void setSummaryBand(SummaryBand sb) {
        summaryBand = sb;
    }

    /**
     * Altera o grupo de dados
     */
    public void setGroup(Group grp) {
        group = grp;
    }

    /**
     * Retorna a fonte de dados
     */
    public ReportData getReportData() {
        return reportData;
    }

    /**
     * Retorna a banda detalhe (dados)
     */
    public DetailBand getDetailBand() {
        return detailBand;
    }

    /**
     * Retorna o cabe�alho
     */
    public HeaderBand getHeaderBand() {
        return headerBand;
    }

    /**
     * Retorna o rodap�
     */
    public FooterBand getFooterBand() {
        return footerBand;
    }

    /**
     * Retorna o t�tulo
     */
    public TitleBand getTitleBand() {
        return titleBand;
    }

    /**
     * Retorna o sum�rio
     */
    public SummaryBand getSummaryBand() {
        return summaryBand;
    }

    /**
     * Retorna o grupo
     */
    public Group getGroup() {
        return group;
    }

    /**
     * Retorna a orienta��o do papel
     */
    public int getOrientation() {
        return orientation;
    }

    /**
     * Adiciona um componente no relat�rio (fora das bandas)
     *
     * @param c o componente
     */
    public void addComponentInReport(Component c) {
        if (c != null) {
            if (componentsInReport == null) {
                componentsInReport = new Vector();
            }

            componentsInReport.addElement(c);
        } else {
            throw new NullPointerException();
        }
    }

    /**
     * Remove um componente do relat�rio (fora das bandas)
     */
    public void removeComponentInReport(Component c) {
        if (c != null && componentsInReport != null) {
            componentsInReport.remove(c);
        } else {
            throw new NullPointerException();
        }
    }

    /**
     * Retorna os componentes do relat�rio (fora da banda)
     */
    public Component[] getComponentInReport() {
        if (componentsInReport != null && componentsInReport.size() > 0) {
            Component[] result = new Component[componentsInReport.size()];

            for (int i = 0; i < componentsInReport.size(); i++) {
                result[i] = (Component) componentsInReport.get(i);
            }

            return result;
        } else {
            return null;
        }
    }

    /**
     * Altera o papel a ser usado pelo relat�rio
     */
    public void setPaper(ReportPaper paper) {
        this.paper = paper;
    }

    /**
     * Retorna o papel
     */
    public ReportPaper getPaper() {
        return paper;
    }

    /**
     * Retorna o n�mero de p�ginas
     */
    public int getNumberOfPages() {
        if (book != null) {
            return book.getNumberOfPages();
        } else {
            return Book.UNKNOWN_NUMBER_OF_PAGES;
        }
    }

    /**
     * Imprimi o relat�rio
     *
     * @param showDialog se o dialogo de configura��o da impressora deve ser mostrado
     */
    public void print(boolean showDialog) throws PrinterException {
        if (book != null) {
            PrinterJob pJob = PrinterJob.getPrinterJob();
            pJob.setPageable(book);

            if (!showDialog || (showDialog && pJob.printDialog())) {
                pJob.print();
            }
        } else {
            throw new ReportRuntimeException("print");
        }
    }

    /**
     * Mostra o relat�rio em tela
     *
     * @param title o t�tulo da tela
     */
    public void show(String title) {
        show(title, "Close");
    }

    /**
     * Mostra o relat�rio em tela
     *
     * @param title o t�tulo da tela
     * @param closeCaption o texto do bot�o "close"
     */
    public void show(String title, String closeCaption) {
        if (book != null) {
            JFrame frame = new JFrame();
            frame.getContentPane().setLayout(new BorderLayout());

            frame.setTitle(title);

            frame.getContentPane().add(new ReportViewerPanel(this, frame, closeCaption), BorderLayout.CENTER);
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

            Insets in = Toolkit.getDefaultToolkit().getScreenInsets(frame.getGraphicsConfiguration());
            Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
            int width = screen.width - (in.left + in.top);
            int height = screen.height - (in.top + in.bottom);
            frame.setBounds(in.left, in.top, width, height);

            frame.setVisible(true);
            frame.validate();
        } else {
            throw new ReportRuntimeException("show");
        }
    }

    /**
     * Retorna uma p�gina como imagem
     * 
     * @param page o n�mero da p�gina
     */
    public java.awt.Image getPageAsImage(int page) {
        if (getOrientation() == LANDSCAPE) {
            getPaper().setSize(getPaper().getHeight(), getPaper().getWidth());
        }

        int width = (int) getPaper().getWidth();
        int height = (int) getPaper().getHeight();
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        paint(bi.createGraphics(), page);

        if (getOrientation() == LANDSCAPE) {
            getPaper().setSize(getPaper().getHeight(), getPaper().getWidth());
        }

        return bi;
    }

    /**
     * Desenha uma p�gina
     *
     * @param graphics o gr�fico
     * @param page o n�mero da p�gina
     */
    public void paint(Graphics graphics, int page) {
        if (book != null) {
            if (page >= 0 && page < book.getNumberOfPages()) {
                try {
                    int width = (int) getPaper().getWidth();
                    int height = (int) getPaper().getHeight();

                    Graphics2D g = (Graphics2D) graphics;
                    g.setColor(Color.white);
                    g.fillRect(0, 0, width, height);
                    g.setColor(Color.black);

                    /*g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
                    g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
                    g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);*/

                    book.getPrintable(page).print(g, pageFormat, page);
                } catch (Exception e) {
                    //throw new RuntimeException("Unexpected error");
                    throw new RuntimeException(e.toString());
                }
            } else {
                throw new RuntimeException("Invalid number page");
            }
        } else {
            throw new ReportRuntimeException("getPage");
        }
    }

    /**
     * Retorna o <i>Book</i> contendo as p�ginas em formato <i>Printable</i>
     */
    public Book getBook() {
        if (book != null) {
            return book;
        } else {
            throw new ReportRuntimeException("getBook");
        }
    }

    /**
     * Erro de relat�rio em <i>runtime</i>
     */
    public class ReportRuntimeException extends RuntimeException {

        final static long serialVersionUID = -14236775475312082L;

        public ReportRuntimeException(String methodCalled) {
            super("Before using " + methodCalled + "() you should use prepare()");
        }
    }

    /**
     * Erro geral de relat�rio
     */
    public class ReportException extends Exception {

        final static long serialVersionUID = -14236775475312081L;
        public static final String NO_COMPONENT = "There is nothing to print.";

        public ReportException(String message) {
            super(message);
        }
    }

    /**
     * Classe que representa o papel que ser� utilizado pelo relat�rio
     */
    public static class ReportPaper extends Paper {

        public ReportPaper(double width, double height, double marginX, double marginY, double marginWidth, double marginHeight) {
            this.setSize(width, height);
            this.setImageableArea(marginX, marginY, marginWidth, marginHeight);
        }

        public ReportPaper(double width, double height, double marginX, double marginY) {
            this(width, height, marginX, marginY, width - (marginX * 2), height - (marginY * 2));
        }
    }

    public String getFontDirectory() {
        return fontDirectory;
    }

    public void setFontDirectory(String s) {
        fontDirectory = s;
    }

    /**
     * Prepara o relat�rio para impress�o ou visualiza��o
     *
     * Desenho da p�gina
     * * Title -> Somente na primeira p�gina
     * * Header
     * * GroupHeader
     * * Detail
     * * GroupFooter
     * * Summary
     * * Footer
     */
    public void prepare() throws ReportException {
        prepare(orientation);
    }

    /**
     * Prepara o relat�rio para impress�o ou visualiza��o
     *
     * Desenho da p�gina
     * * Title -> Somente na primeira p�gina
     * * Header
     * * GroupHeader
     * * Detail
     * * GroupFooter
     * * Summary
     * * Footer
     */
    public void prepare(int orientation) throws ReportException {
        Vector design;

        pageFormat = new PageFormat();
        pageFormat.setOrientation(orientation);
        pageFormat.setPaper(paper);

        int width;
        int height;

        if (orientation == LANDSCAPE) {
            width = (int) Math.floor(paper.getImageableHeight());
            height = (int) Math.floor(paper.getImageableWidth());
        } else {
            width = (int) Math.floor(paper.getImageableWidth());
            height = (int) Math.floor(paper.getImageableHeight());
        }

        this.orientation = orientation;

        if (reportData != null && detailBand != null) {
            int leftInPage = height, footerHeight = 0;
            int pageNumber = 0;
            int dataRow = 0;
            Object lastGroupValue = null;
            boolean showGroupHeader = true, header = true, title = true;
            Component[] c = getComponentInReport();

            book = new Book();
            design = new Vector();

            // set "width" of all the bands ***************************
            if (titleBand != null) {
                titleBand.setSize(width, titleBand.getHeight());
            }
            if (headerBand != null) {
                headerBand.setSize(width, headerBand.getHeight());
            }
            if (group != null) {
                group.getHeaderBand().setSize(width, group.getHeaderBand().getHeight());
            }
            if (detailBand != null) {
                detailBand.setSize(width, detailBand.getHeight());
            }
            if (group != null) {
                group.getFooterBand().setSize(width, group.getFooterBand().getHeight());
            }
            if (summaryBand != null) {
                summaryBand.setSize(width, summaryBand.getHeight());
            }
            if (footerBand != null) {
                footerBand.setSize(width, footerBand.getHeight());
            }

            Object[] obj = new Object[]{new Integer(0), reportData, this};

            if (footerBand != null) {
                footerBand.doLayout();
                footerBand.prepareAll(pageNumber, obj);
                footerHeight = footerBand.getHeight();
            }

            int i;

            if (reportData.size() == 0) {
                if (titleBand != null && title) {
                    titleBand.doLayout();
                    titleBand.prepareAll(pageNumber, obj);
                    leftInPage -= titleBand.getHeight();

                    design.addElement(titleBand);

                    title = false;
                }

                if (headerBand != null && header) { // add header band
                    headerBand.doLayout();
                    headerBand.prepareAll(pageNumber, obj);
                    leftInPage -= headerBand.getHeight();

                    design.addElement(headerBand);

                    header = false;
                }
            }

            for (i = 0; i < reportData.size(); i++) { // pass through all data

                obj = new Object[]{new Integer(i), reportData, this};

                // first page **********************************************
                if (pageNumber == 0) { // first page only...
                    if (titleBand != null && title) {
                        titleBand.doLayout();
                        titleBand.prepareAll(pageNumber, obj);
                        leftInPage -= titleBand.getHeight();

                        design.addElement(titleBand);

                        title = false;
                    }

                    if (headerBand != null && header) { // add header band
                        headerBand.doLayout();
                        headerBand.prepareAll(pageNumber, obj);
                        leftInPage -= headerBand.getHeight();

                        design.addElement(headerBand);

                        header = false;
                    }
                }

                // put the group footer ************************************************************
                if (!showGroupHeader && group != null) {
                    if ((lastGroupValue == null && reportData.get(i, group.getField()) != null) || (lastGroupValue != null && !lastGroupValue.equals(reportData.get(i, group.getField())))) {
                        group.getFooterBand().doLayout();
                        group.getFooterBand().prepareAll(pageNumber, obj);

                        /*************************************************************/
                        /************************ CREATE A NEW PAGE ******************/
                        /*************************************************************/
                        if (leftInPage < (group.getFooterBand().getHeight() + footerHeight)) {
                            if (footerBand != null) { // add footer band
                                footerBand.doLayout();
                                footerBand.prepareAll(pageNumber, obj);

                                design.addElement(footerBand);
                            }

                            book.append(new ReportPrinter(this, design, c, reportData, dataRow), pageFormat);

                            design = new Vector();
                            leftInPage = height;
                            pageNumber++;
                            dataRow = i;

                            if (headerBand != null) { // add header band
                                headerBand.doLayout();
                                headerBand.prepareAll(pageNumber, obj);
                                leftInPage -= headerBand.getHeight();

                                design.addElement(headerBand);
                            }
                        }
                        /*************************************************************/
                        /*************************************************************/
                        /*************************************************************/
                        leftInPage -= group.getFooterBand().getHeight();

                        design.addElement(group.getFooterBand());

                        lastGroupValue = reportData.get(i, group.getField());
                        showGroupHeader = true;
                    }
                }

                // put the group header ************************************************************
                if (showGroupHeader && group != null) {
                    if (lastGroupValue == null) {
                        lastGroupValue = reportData.get(i, group.getField());
                    }

                    group.getHeaderBand().doLayout();
                    group.getHeaderBand().prepareAll(pageNumber, obj);

                    /*************************************************************/
                    /************************ CREATE A NEW PAGE ******************/
                    /*************************************************************/
                    if (leftInPage < (group.getHeaderBand().getHeight() + footerHeight)) {
                        if (footerBand != null) { // add footer band
                            footerBand.doLayout();
                            footerBand.prepareAll(pageNumber, obj);

                            design.addElement(footerBand);
                        }

                        book.append(new ReportPrinter(this, design, c, reportData, dataRow), pageFormat);

                        design = new Vector();
                        leftInPage = height;
                        pageNumber++;
                        dataRow = i;

                        if (headerBand != null) { // add header band
                            headerBand.doLayout();
                            headerBand.prepareAll(pageNumber, obj);
                            leftInPage -= headerBand.getHeight();

                            design.addElement(headerBand);
                        }
                    }
                    /*************************************************************/
                    /*************************************************************/
                    /*************************************************************/
                    leftInPage -= group.getHeaderBand().getHeight();

                    design.addElement(group.getHeaderBand());

                    showGroupHeader = false;
                }

                // put detail ************************************************************
                detailBand.doLayout();
                detailBand.prepareAll(pageNumber, obj);

                /*************************************************************/
                /************************ CREATE A NEW PAGE ******************/
                /*************************************************************/
                if (leftInPage < (detailBand.getHeight() + footerHeight)) {
                    if (footerBand != null) { // add footer band
                        footerBand.doLayout();
                        footerBand.prepareAll(pageNumber, obj);

                        design.addElement(footerBand);
                    }

                    book.append(new ReportPrinter(this, design, c, reportData, dataRow), pageFormat);

                    design = new Vector();
                    leftInPage = height;
                    pageNumber++;
                    dataRow = i;

                    if (headerBand != null) { // add header band
                        headerBand.doLayout();
                        headerBand.prepareAll(pageNumber, obj);
                        leftInPage -= headerBand.getHeight();

                        design.addElement(headerBand);
                    }
                }
                /*************************************************************/
                /*************************************************************/
                /*************************************************************/
                leftInPage -= detailBand.getHeight();

                design.addElement(detailBand);

            }

            // prepare the last page ************************************************

            obj = new Object[]{new Integer(i), reportData, this};

            // insert group footer *********
            if (group != null) {
                group.getFooterBand().doLayout();
                group.getFooterBand().prepareAll(pageNumber, obj);

                /*************************************************************/
                /************************ CREATE A NEW PAGE ******************/
                /*************************************************************/
                if (leftInPage < (group.getFooterBand().getHeight() + footerHeight)) {
                    if (footerBand != null) { // add footer band
                        footerBand.doLayout();
                        footerBand.prepareAll(pageNumber, obj);
                        design.addElement(footerBand);
                    }

                    book.append(new ReportPrinter(this, design, c, reportData, dataRow), pageFormat);

                    design = new Vector();
                    leftInPage = height;
                    pageNumber++;

                    if (headerBand != null) { // add header band
                        headerBand.doLayout();
                        headerBand.prepareAll(pageNumber, obj);
                        leftInPage -= headerBand.getHeight();
                        design.addElement(headerBand);
                    }
                }
                /*************************************************************/
                /*************************************************************/
                /*************************************************************/
                leftInPage -= group.getFooterBand().getHeight();
                design.addElement(group.getFooterBand());
            }

            // put summary band ***********
            if (summaryBand != null) {
                summaryBand.doLayout();
                summaryBand.prepareAll(pageNumber, obj);

                /*************************************************************/
                /************************ CREATE A NEW PAGE ******************/
                /*************************************************************/
                if (leftInPage < (summaryBand.getHeight() + footerHeight) || summaryBand.getCreateNewPage()) {
                    if (footerBand != null) { // add footer band
                        footerBand.doLayout();
                        footerBand.prepareAll(pageNumber, obj);

                        design.addElement(footerBand);
                    }

                    book.append(new ReportPrinter(this, design, c, reportData, dataRow), pageFormat);

                    design = new Vector();
                    leftInPage = height;
                    pageNumber++;

                    if (headerBand != null) { // add header band
                        headerBand.doLayout();
                        headerBand.prepareAll(pageNumber, obj);
                        leftInPage -= headerBand.getHeight();

                        design.addElement(headerBand);
                    }
                }
                /*************************************************************/
                /*************************************************************/
                /*************************************************************/
                design.addElement(summaryBand);
            }

            // insert page footer **************
            if (footerBand != null) { // add footer band
                footerBand.doLayout();
                footerBand.prepareAll(pageNumber, obj);

                design.addElement(footerBand);
            }

            book.append(new ReportPrinter(this, design, c, reportData, dataRow), pageFormat);
        } else if (summaryBand != null) {
            design = new Vector();
            summaryBand.setSize(width, height);
            design.addElement(summaryBand);

            book = new Book();
            book.append(new ReportPrinter(this, design, getComponentInReport()), pageFormat);
        } else if (componentsInReport != null && componentsInReport.size() > 0) {
            book = new Book();
            book.append(new ReportPrinter(this, null, getComponentInReport()), pageFormat);
        } else {
            throw new ReportException(ReportException.NO_COMPONENT);
        }
    }
}
